package com.ibeeking.found.open.b.rest.service.impl;

import com.ibeeking.found.common.config.feign.GlobalClient;
import com.ibeeking.found.common.entity.KeyValue;
import com.ibeeking.found.common.entity.TenantDTO;
import com.ibeeking.found.common.enums.goods.GoodsChannelEnum;
import com.ibeeking.found.open.api.common.dto.*;
import com.ibeeking.found.open.api.common.param.CouponVerificationParam;
import com.ibeeking.found.open.api.common.param.ModifyCouponStatusParam;
import com.ibeeking.found.open.api.common.query.ConfirmOrderCouponQuery;
import com.ibeeking.found.open.api.common.query.ConfirmOrderGoodsQuery;
import com.ibeeking.found.open.api.common.query.CouponInfoQuery;
import com.ibeeking.found.open.api.feign.MarketingFeignClient;
import com.ibeeking.found.open.b.rest.service.ICouponService;
import com.ibeeking.found.open.b.rest.service.ISystemService;
import com.ibeeking.found.open.service.common.dto.CouponVerificationChannelListDTO;
import com.ibeeking.found.open.service.common.param.CouponVerificationQRParam;
import com.ibeeking.found.open.service.common.query.CouponLockQuery;
import com.ibeeking.found.open.service.common.query.CouponSuperpositionQuery;
import com.ibeeking.found.open.service.common.query.CouponUnLockQuery;
import com.ibeeking.found.open.service.common.query.CouponVerificationQuery;
import com.ibeeking.nematos.constants.enums.LogConstant;
import com.ibeeking.nematos.exception.BusinessException;
import com.ibeeking.nematos.exception.DataNotExistException;
import com.ibeeking.nematos.log.utils.LogUtils;
import com.ibeeking.nematos.utils.bean.BeanUtil;
import com.ibeeking.nematos.utils.data.Collections3;
import com.ibeeking.nematos.utils.data.DataUtils;
import com.ibeeking.nematos.utils.json.JsonUtils;
import com.ibeeking.nematos.utils.result.ResponseCodeEnum;
import com.ibeeking.nematos.utils.result.ResponseResult;
import org.apache.logging.log4j.ThreadContext;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

import static java.math.BigDecimal.ROUND_HALF_UP;
import static java.math.BigDecimal.ROUND_UNNECESSARY;

/**
 * @ClassName CouponServiceImpl
 * @Description
 * @Author ibeeking
 * @Date 2021-06-15 11:18
 **/
@Service
public class CouponServiceImpl implements ICouponService {

    @Resource
    private MarketingFeignClient marketingFeignClient;
    @Resource
    private ISystemService systemServiceImpl;
    @Resource
    private GlobalClient globalClient;

    @Override
    public List<CouponTypeListDTO> couponType() {
        ResponseResult<List<KeyValue<Integer, String>>> responseResult = marketingFeignClient.queryCouponTypes();
        if (!ResponseCodeEnum.SUCCESS.getCode().equals(responseResult.getCode())) {
            return Collections3.emptyList();
        }
        List<CouponTypeListDTO> result = new ArrayList<>();
        responseResult.getData().forEach(s -> {
            CouponTypeListDTO couponTypeListDTO = new CouponTypeListDTO();
            couponTypeListDTO.setId(s.getKey().longValue());
            couponTypeListDTO.setCode(String.valueOf(s.getKey()));
            couponTypeListDTO.setLable(s.getValue());
            result.add(couponTypeListDTO);
        });
        return result;
    }

    @Override
    public List<CouponVerificationChannelListDTO> verificationChannel() {
        ResponseResult<List<KeyValue<Integer, String>>> responseResult = marketingFeignClient.queryVerificationChannel();
        if (!ResponseCodeEnum.SUCCESS.getCode().equals(responseResult.getCode())) {
            return Collections3.emptyList();
        }
        List<CouponVerificationChannelListDTO> result = new ArrayList<>();
        responseResult.getData().forEach(s -> {
            CouponVerificationChannelListDTO couponTypeListDTO = new CouponVerificationChannelListDTO();
            couponTypeListDTO.setId(s.getKey().longValue());
            couponTypeListDTO.setCode(String.valueOf(s.getKey()));
            couponTypeListDTO.setLable(s.getValue());
            result.add(couponTypeListDTO);
        });
        return result;
    }

    @Override
    public CouponInfoDTO queryCouponInfoByCouponCode(Long couponCode) {
        ResponseResult<MemberCouponInfoDTO> responseResult = marketingFeignClient.queryCouponInfoByCouponCode(couponCode);
        MemberCouponInfoDTO data = responseResult.getData();
        if (data == null || !ResponseCodeEnum.SUCCESS.getCode().equals(responseResult.getCode())) {
            throw new BusinessException("未查询到券信息!");
        }
        CouponInfoDTO result = BeanUtil.convertBean(data, CouponInfoDTO.class);
        result.setPromotionId(data.getCouponId());
        result.setPromotionName(data.getName());
        result.setValidityStartTime(data.getStartTime());
        result.setValidityEndTime(data.getEndTime());
        result.setVerification(data.getVerificationStatus());
        result.setStatus(1 == data.getCouponStatus() && 1 == data.getVerificationStatus() ? 1 : 2);
        result.setStoreOpenStatus(result.getStatus());
        result.setCouponType(data.getCouponTypeCode());
        result.setParValue(DataUtils.fromFenToYuan(data.getWorth(), 2, ROUND_UNNECESSARY));
        return result;
    }

    @Override
    public Boolean couponLock(CouponLockQuery query) {
        ModifyCouponStatusParam param = new ModifyCouponStatusParam();
        param.setMemberId(query.getMemberId());
        param.setCouponCodes(query.getCouponCodes());
        ResponseResult<Boolean> responseResult = marketingFeignClient.lockCoupon(param);
        if (!ResponseCodeEnum.SUCCESS.getCode().equals(responseResult.getCode())) {
            return false;
        }
        return responseResult.getData();
    }

    @Override
    public Boolean couponUnLock(CouponUnLockQuery query) {
        ModifyCouponStatusParam param = new ModifyCouponStatusParam();
        param.setMemberId(query.getMemberId());
        param.setCouponCodes(query.getCouponCodes());
        ResponseResult<Boolean> responseResult = marketingFeignClient.unLockCoupon(param);
        if (!ResponseCodeEnum.SUCCESS.getCode().equals(responseResult.getCode())) {
            return false;
        }
        return responseResult.getData();
    }

    @Override
    public Boolean couponVerification(CouponVerificationQuery query) {
        List<CouponVerificationParam> params = new ArrayList<>();
        CouponVerificationParam param = new CouponVerificationParam();
        param.setMemberId(query.getMemberId());
        param.setVerificationChannel(query.getChannel());
        param.setShopId(systemServiceImpl.queryShopIdByShopCode(query.getShopCode()));
        param.setCouponCodes(query.getCouponCodes());
        params.add(param);
        ResponseResult<Boolean> responseResult = marketingFeignClient.verificationCoupon(params);
        if (!ResponseCodeEnum.SUCCESS.getCode().equals(responseResult.getCode())) {
            return false;
        }
        return responseResult.getData();
    }

    @Override
    public Boolean verificationCouponByQR(CouponVerificationQRParam param) {
        com.ibeeking.found.open.api.common.param.CouponVerificationQRParam param1 = new com.ibeeking.found.open.api.common.param.CouponVerificationQRParam();
        param1.setCouponQRCode(param.getCouponQRCode());
        param1.setShopId(systemServiceImpl.queryShopIdByShopCode(param.getShopCode()));
        param1.setCouponAmount(DataUtils.fromYuanToFen(DataUtils.scale(param.getCouponAmount(), 2, ROUND_HALF_UP)));
        ResponseResult<Boolean> responseResult = marketingFeignClient.verificationCouponByQr(param1);
        if (!ResponseCodeEnum.SUCCESS.getCode().equals(responseResult.getCode()) || responseResult.getData() == null || !responseResult.getData()) {
            com.ibeeking.found.common.utils.DataUtils.trueThrowException(true, responseResult.getMsg());
        }
        return responseResult.getData();
    }

    @Override
    public CouponInfoDTO queryCouponInfo(CouponInfoQuery query) {
        //根据券二维码/条码查询
        ResponseResult<MemberCouponQRDTO> responseResult = marketingFeignClient.queryCouponCodeByQRCode(query.getCouponQRCode());
        if (responseResult.getData() == null || !ResponseCodeEnum.SUCCESS.getCode().equals(responseResult.getCode())) {
            throw new DataNotExistException("券码不正确或已过期，请刷新券码后再试");
        }
        return queryCouponInfoByCouponCode(responseResult.getData().getCouponCode());
    }

    @Override
    public CouponInfoDTO couponInfoById(String marketCode, CouponInfoQuery query) {
        //查询租户id
        ResponseResult<TenantDTO> responseResult = globalClient.queryTenantByCode(marketCode);
        if (!ResponseCodeEnum.SUCCESS.getCode().equals(responseResult.getCode())) {
            return new CouponInfoDTO();
        }
        ThreadContext.put(LogConstant.TENANT_ID, String.valueOf(responseResult.getData().getId()));
        try {
            //根据券二维码/条码查询
            return queryCouponInfo(query);
        } finally {
            ThreadContext.remove(LogConstant.TENANT_ID);
        }
    }

    @Override
    public Boolean verificationById(String marketCode, CouponVerificationQRParam param) {
        //查询租户id
        ResponseResult<TenantDTO> responseResult = globalClient.queryTenantByCode(marketCode);
        if (!ResponseCodeEnum.SUCCESS.getCode().equals(responseResult.getCode()) || responseResult.getData() == null) {
            com.ibeeking.found.common.utils.DataUtils.trueThrowException(true, "核销失败!(无法获取商场信息)");
        }
        ThreadContext.put(LogConstant.TENANT_ID, String.valueOf(responseResult.getData().getId()));
        try {
            return verificationCouponByQR(param);
        } finally {
            ThreadContext.remove(LogConstant.TENANT_ID);
            ThreadContext.remove(LogConstant.USER_ID);
        }
    }

    @Override
    public MemberCouponSuperpositionDTO superposition(CouponSuperpositionQuery query) {
        ThreadContext.put(LogConstant.USER_ID, String.valueOf(query.getMemberId()));
        try {
            Long shopId = systemServiceImpl.queryShopIdByShopCode(query.getShopCode());
            ConfirmOrderCouponQuery query1 = new ConfirmOrderCouponQuery();
            query1.setCouponCodes(query.getCouponCodes());
            List<ConfirmOrderGoodsQuery> queries = new ArrayList<>();
            query.getGoods().forEach(s -> {
                ConfirmOrderGoodsQuery query2 = new ConfirmOrderGoodsQuery();
                query2.setChannel(GoodsChannelEnum.POS.getValue());
                query2.setShopId(shopId);
                query2.setGoodsId(s.getGoodsId());
                query2.setGoodsSkuId(s.getGoodsSkuId());
                query2.setQty(s.getQty());
                query2.setPrice(s.getPrice());
                query2.setPoints(0);
                queries.add(query2);
            });
            query1.setConfirmOrderGoodsQueries(queries);
            ResponseResult<ConfirmOrderCouponDTO> responseResult = marketingFeignClient.confirmOrderCoupon(query1);
            if (!ResponseCodeEnum.SUCCESS.getCode().equals(responseResult.getCode())) {
                LogUtils.error("查询会员券异常:[{}]", JsonUtils.toJsonStr(responseResult));
                throw new BusinessException("查询会员券异常");
            }
            ConfirmOrderCouponDTO data = responseResult.getData();
            MemberCouponSuperpositionDTO result = new MemberCouponSuperpositionDTO();
            result.setCheckResult(true);
            List<Long> select = data.getSelect();
            select.addAll(data.getAvailable());
            result.setUsableCouponCodes(select);
            result.setDisusableCouponCodes(data.getNotAvailable());
            return result;
        } finally {
            ThreadContext.remove(LogConstant.USER_ID);
        }
    }
}
